﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VsxFactory.Modeling.StrategyManager.Dialog;
using VsxFactory.Modeling.Repository;

namespace VsxFactory.Modeling.StrategyManager
{
    public class VsPackageSourceProvider : IPackageSourceProvider
    {
        //internal static readonly PackageSource AggregateSource = new PackageSource("All", "(Aggregate source)") { IsAggregate = true };

        private readonly IPackageSourceSettingsManager _settingsManager;

        private List<PackageSource> _packageSources;
        private PackageSource _activePackageSource;

        public VsPackageSourceProvider(IPackageSourceSettingsManager settingsManager)
        {
            _settingsManager = settingsManager;

            DeserializePackageSources();
            DeserializeActivePackageSource();
        }

        public PackageSource ActivePackageSource
        {
            get
            {
                return _activePackageSource;
            }
            set
            {
                if (value != null && !_packageSources.Contains(value))
                {
                    throw new ArgumentException("Invalid package source", "value");
                }

                _activePackageSource = value;

                // persist the value into VS settings store
                _settingsManager.ActivePackageSourceString = value == null ? null : value.Name;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage(
            "Microsoft.Design",
            "CA1024:UsePropertiesWhereAppropriate",
            Justification = "This method is potentially expensive because we are retrieving data from VS settings store.")]
        public IEnumerable<PackageSource> GetPackageSources()
        {
            return _packageSources;
        }

        public void AddPackageSource(PackageSource source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!_packageSources.Contains(source))
            {
                _packageSources.Add(source);

                // if the package source that we just added is the only one, make it the default
                if (ActivePackageSource == null && _packageSources.Count == 1)
                {
                    ActivePackageSource = source;
                }

                PersistPackageSources();
            }
        }

        public bool RemovePackageSource(PackageSource source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            bool result = _packageSources.Remove(source);
            if (result)
            {
                PersistPackageSources();
                if (source.Equals(ActivePackageSource))
                {
                    ActivePackageSource = null;
                }
            }

            return result;
        }

        public void SetPackageSources(IEnumerable<PackageSource> sources)
        {
            _packageSources.Clear();
            ActivePackageSource = null;

            if (sources != null)
            {
                foreach (var s in sources)
                {
                    _packageSources.Add(s);
                }
            }

            PersistPackageSources();
        }

        private void PersistPackageSources()
        {
            StringBuilder data = new StringBuilder();
            foreach (var src in _packageSources)
            {
                data.AppendFormat("{0}={1}|", src.Name, src.Source);
            }
            _settingsManager.PackageSourcesString = data.ToString();
        }

        private void DeserializePackageSources()
        {
            _packageSources = new List<PackageSource>();
            string propertyString = _settingsManager.PackageSourcesString;

            if (!String.IsNullOrEmpty(propertyString))
            {
                foreach (var part in propertyString.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var segments = part.Split('=');
                    _packageSources.Add(new PackageSource(segments[0], segments[1]));
                }
            }

            if (_packageSources == null)
            {
                _packageSources = new List<PackageSource>();
            //    _packageSources.Add(AggregateSource);
            //}
            //else if (!_packageSources.Contains(AggregateSource))
            //{
            //    _packageSources.Insert(0, AggregateSource);
            }
        }

        private void DeserializeActivePackageSource()
        {
            var packageSource = _packageSources.FirstOrDefault(p => p.Name == _settingsManager.ActivePackageSourceString);
            if (packageSource != null)
            {
                // this is to guard against corrupted VS user settings store
                AddPackageSource(packageSource);

                ActivePackageSource = packageSource;
            }
            else if (_settingsManager.IsFirstRunning)
            {
                packageSource = _settingsManager.DefaultRepositorySource;
                if (packageSource != null)                
                    AddPackageSource(packageSource);
                _settingsManager.IsFirstRunning = false;                
            }
        }
    }
}
